/****************************************************************************
   Copyright 2013 Stacy Doss

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
****************************************************************************/

#ifndef SPARSE_SHARED_H
#define SPARSE_SHARED_H

#include <map>
#include <string>
#include <vector>

int line_number=1;

struct Node {
    int                                  ival;
    float                                fval;
    std::string                         *name;
    std::vector<std::string*>           *vec_str;
    std::vector<double>                 *vec_dbl;
    std::vector<int>                    *vec_int;
    std::map<std::string, std::string*> *map_str;
    std::map<std::string, double>       *map_dbl;
    std::map<std::string, int>          *map_int;
};


struct StrVector;
struct GrpMap;

struct DblAttribute {
  std::string name;
  double      value;
  DblAttribute(std::string n, double v) {
    name = n;
    value = v;
  }
};

struct IntAttribute {
  std::string name;
  int         value;
  IntAttribute(std::string n, int v) {
    name = n;
    value = v;
  }
};

struct StrAttribute {
  std::string name;
  std::string value;
  StrAttribute(std::string n, std::string v) {
    name = n;
    value = v;
  }
};

struct CmplxAttribute {
  std::string name;
  StrVector   *values;
  CmplxAttribute(std::string n) {
    name = n;
  }
  // Really want this to add strings (dbl/ints) as needed
  int add(StrVector *v) {
    values = v;
  }
};

struct DblVector {
  std::vector<double> *values;
  DblVector() {
    values = new std::vector<double>;
  }
};

struct IntVector {
  std::vector<int> *values;
  IntVector() {
    values = new std::vector<int>;
  }
};

struct StrVector {
  std::vector<std::string> *values;
  StrVector() {
    values = new std::vector<std::string>;
  }
  int push_back(std::string v) {
    values->push_back(v);
  }
};

struct Group {
  std::string name;
  std::string id;
  std::vector<GrpMap*> * values;
  Group (std::string n, std::string i) {
    name = n;
    id   = i;
    values = new std::vector<GrpMap*>;
  }
  int add(GrpMap* v) {
    values->push_back(v);
  }
};


struct GrpMap {
  std::map<std::string, double>      *da;
  std::map<std::string, int>         *ia;
  std::map<std::string, std::string> *sa;
  std::map<std::string, StrVector* > *ca;
  std::map<std::string, std::map<std::string, std::vector<Group*>* > * > *grp;

  GrpMap() {
    da  = new std::map<std::string, double>;
    ia  = new std::map<std::string, int>;
    sa  = new std::map<std::string, std::string>;
    ca  = new std::map<std::string, StrVector* >;
    grp = new std::map<std::string, std::map<std::string, std::vector<Group*> * > *>;
  }

  int add(DblAttribute *v) {
    (*da)[v->name] = v->value;
  }

  int add(IntAttribute *v) {
    (*ia)[v->name] = v->value;
  }

  int add(StrAttribute *v) {
    (*sa)[v->name] = v->value;
  }

  int add(CmplxAttribute *v) {
    (*ca)[v->name] = v->values;
  }

  int add(Group* v) {
    if (!(*grp)[v->name]) {
      (*grp)[v->name] = new std::map< std::string, std::vector<Group*> * >;
    };

    if(!(*(*grp)[v->name])[v->id]) {
      (*(*grp)[v->name])[v->id] = new std::vector<Group*>;
    }

    (*(*grp)[v->name])[v->id]->push_back(v);
  }


};



#endif
